package com.yunding.util;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunding.entity.SysAuth;
import com.yunding.entity.SysUser;
import com.yunding.enums.ResultStatuesEnums;
import com.yunding.exception.ServiceException;
import com.yunding.mapper.SysUserMapper;
import com.yunding.mapper.UserAuthMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;

/**
 * @author: 郭思良
 * @date: 2020/2/8 18:25
 */
@Slf4j
public class ShiroRealm extends AuthorizingRealm {

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private UserAuthMapper sysAuthMapper;



    /**
     * 进行权限管理、授权验证
     *
     *
     * @param principals shiro封装的
     * @return 返回带有角色信息的info
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {


//        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//        /*
//         * 获得用户的principal，里面存入了当前用户的所有权限和角色
//         */
//        Subject subject = SecurityUtils.getSubject();
//        ActivityAdminUser principal = (ActivityAdminUser) subject.getPrincipal();
//        /*
//         * 获得了用户权限的set集合
//         */
//        Set<String> permissions = principal.getPermissions().stream().map(AdminPermission::getName).collect(Collectors.toSet());
//        Set<String> roles = principal.getRoles().stream().map(AdminRole::getName).collect(Collectors.toSet());
//
//        simpleAuthorizationInfo.addStringPermissions(permissions);
//        simpleAuthorizationInfo.addRoles(roles);
//
//        return simpleAuthorizationInfo;
        return null;
    }



    /**
     * 进行的登录管理、登录认证
     *
     *
     * @param token shiro封装的UserPasswordToken
     * @return 返回shiro封装的info，存入了当前用户的信息
     * @throws AuthenticationException 在登录认证的过程中出现了密码错误、用户名错误等异常会在login方法中抛出
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        /*
         * 通过token.getPrincipal方法得到Login方法时传入UsernamePasswordToken中的username-->这里是mobile
         */
        String currentMobile = (String) token.getPrincipal();

        /*
         * 判断用户是否不存在,返回的是SysAuth的对象
         */
        SysAuth user = ensureUserExist(currentMobile);

        /*
         * 判断用户是否被锁定，返回的是AdminUser的对象
         */
        SysUser adminUser = ensureUserLocked(currentMobile);


        /*
         *
         * 这个方法是用来做密码匹配的
         *
         * 这个类的构造方法有参数3个的还有参数4个的。
         * 首先第一个参数可以为任意类型的任意值，通常是getPrincipal方法得到的用户名
         *     由于授权认证时需要多次执行授权认证流程，所以将用户、角色、权限封装成对象直接传过去
         *     就避免了多次访问doGetAuthorizationInfo方法
         * 第二个参数使用 查询到的用户密码，而不是前台传来的密码
         * 第三个（salt） 是加盐加密时使用的盐值 ByteSource类型的
         * 第四个参数： this.getName()方法,该类的类名
         */
        return new SimpleAuthenticationInfo(adminUser, user.getPasswd(),this.getName());
    }


    /**
     * 判断用户是否被禁用
     *
     *
     * @param currentMobile 当前subject的手机号
     * @return 返回数据库查出的用户信息
     */
    private SysUser ensureUserLocked(String currentMobile) {
        SysUser adminUser = sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("user_phone", currentMobile));

        /*
         * 判断用户是否被锁定
         */
//        if (adminUser.getUserStatus() != 0){
//            throw new ServiceException(ResultStatuesEnums.USER_LOCKED);
//        }
        return adminUser;
    }

    /**
     * 判断用户是否存在
     *
     *
     * @param currentMobile 当前subject的手机号
     * @return 返回数据库查出用于用户验证的对象
     */
    private SysAuth ensureUserExist(String currentMobile) {
        /*
           Shiro认证流程是首先获得用户名，查询数据库获得实体User类，在做密码匹配
         */
        SysAuth user = sysAuthMapper.selectOne(new QueryWrapper<SysAuth>().eq(SysAuth.COL_USER_PHONE, currentMobile));

        if (user == null) {
            throw new ServiceException(ResultStatuesEnums.USER_NOT_EXIST);
        }

        return user;
    }

    /**
     * 将用户本身的角色和用户组的角色合并,查询出所有的权限，赋值给ActivityAdminUser
     *
     *
     * @param user 用户对象
     * @return 返回用户所有的角色id
     */
//    private ActivityAdminUser getAllRoleRights(AdminUser user) {
//
//        /*
//         * AdminDept不在存储角色、所以不必再查询dept的id和其角色了
//         * 思路：首先通过adminUserRole找出来该用户的普通角色
//         * 通过adminRolePermission和adminUserPermission查找出用户本身具有的权限和角色赋予的权限
//         */
//
//        //从数据库中查到该用户所拥有的角色,取出AdminUserRole集合中的id属性，存入到另一个list集合中
//        List<Long> roleIds = adminUserRoleMapper.selectList(new QueryWrapper<AdminUserRole>().
//                eq(AdminUserRole.COL_USER_ID, user.getId())).stream().map(AdminUserRole::getRoleId).collect(Collectors.toList());
//
//        //根据roleId获得Role对象
//        List<AdminRole> roles = adminRoleMapper.selectBatchIds(roleIds);
//
//        /*
//         * 查找角色对应的权限和用户对应的特殊权限
//         */
//        List<AdminRolePermission> rolePermissions = adminRolePermissionMapper.selectList(new QueryWrapper
//                <AdminRolePermission>().in(AdminRolePermission.COL_ROLE_ID, roleIds));
//        List<AdminUserPermission> userPermissions = adminUserPermissionMapper.selectList(new QueryWrapper
//                <AdminUserPermission>().eq(AdminUserPermission.COL_USER_ID, user.getId()));
//
//        //获得角色对应的权限id和用户特殊权限id，将这两种id合并起来
//        Set<Long> permissionSet = rolePermissions.stream().map(AdminRolePermission::getPermissionId).collect(Collectors.toSet());
//        permissionSet.addAll(userPermissions.stream().map(AdminUserPermission::getPermissionId).collect(Collectors.toSet()));
//
//        List<AdminPermission> permissions = new ArrayList<>();
//
//        //通过合并来的id的集合，获得Permission对象
//        //如果permissionSet为空的话，SQL语句会报错
//        if(!CollectionUtils.isEmpty(permissionSet)){
//            permissions = adminPermissionMapper.selectBatchIds(permissionSet);
//        }
//
//
//        return ActivityAdminUser.builder().user(user).roles(roles).permissions(permissions).build();
//    }
}
